package com.wgz.flag.service.impl;

import com.wgz.flag.domain.dto.ContactDto;
import com.wgz.flag.domain.dto.ContactRequestDto;
import com.wgz.flag.domain.vo.ContactVo;
import com.wgz.flag.domain.vo.FriendRequestVo;
import com.wgz.flag.entity.Contact;
import com.wgz.flag.entity.FriendRequest;
import com.wgz.flag.entity.User;
import com.wgz.flag.mapper.ContactMapper;
import com.wgz.flag.mapper.FriendRequestMapper;
import com.wgz.flag.mapper.UserMapper;
import com.wgz.flag.service.ContactService;
import com.wgz.flag.websocket.ChatWebSocketServer;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ContactServiceImpl implements ContactService {

    private final ContactMapper contactMapper;
    private final FriendRequestMapper friendRequestMapper;
    private final ChatWebSocketServer webSocketServer;
    @Autowired
    private UserMapper userMapper;

    /**
     * 根据用户id获取联系人列表
     *
     * @param userId 用户id
     * @return 联系人列表
     */
    @Override
    public List<ContactVo> getContactList(Long userId) {
        List<Contact> contacts = contactMapper.selectByUserId(userId);
        return contacts.stream().map(contact -> {
            ContactVo vo = new ContactVo();
            BeanUtils.copyProperties(contact, vo);
            if (contact.getFriend() != null) {
                vo.setUsername(contact.getFriend().getUsername());
                vo.setNickname(contact.getFriend().getNickname());
                vo.setAvatar(contact.getFriend().getAvatar());
            }
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void addContact(Long userId, ContactDto contactDto) {
        // 检查 contactDto 是否包含 friendId
        if (contactDto.getFriendId() == null) {
            throw new IllegalArgumentException("friendId cannot be null");
        }

//        // 检查是否存在相同的 userId 和 friendId 组合
//        Contact existingContact = contactMapper.selectByUserIdAndFriendId(userId, contactDto.getFriendId());
//        if (existingContact != null) {
//            // 处理已存在的记录，更新状态为同意
//            existingContact.setStatus(1);
//            contactMapper.update(existingContact);
//            return;
//        }

        Contact contact = new Contact();
        contact.setUserId(userId);
        BeanUtils.copyProperties(contactDto, contact);

        // 手动设置 friendId
        contact.setFriendId(contactDto.getFriendId());
        contactMapper.insert(contact);
    }

    @Override
    @Transactional
    public void updateContact(Long userId, Long friendId, ContactDto contactDto) {
        Contact contact = contactMapper.selectByUserIdAndFriendId(userId, friendId);
        contact.setRemark(contactDto.getRemark());
        contact.setCategory(contactDto.getCategory());
        contactMapper.update(contact);
    }

    @Override
    @Transactional
    public void deleteContact(Long userId, Long friendId) {
        Contact contact = contactMapper.selectByUserIdAndFriendId(userId, friendId);
        contactMapper.delete(contact.getId());
    }

    /**
     * 发送好友请求
     * @param userId
     * @param requestDto
     */
    @Override
    public void sendFriendRequest(Long userId, ContactRequestDto requestDto) {
        FriendRequest request = new FriendRequest();
        request.setFromUserId(userId);
        request.setToUserId(requestDto.getFriendId());
        request.setRemark(requestDto.getApplyReason());

        friendRequestMapper.insert(request);

        // 通过WebSocket通知接收方
        webSocketServer.sendMessage(requestDto.getFriendId(),
                "NEW_FRIEND_REQUEST", request);
    }

    @Override
    @Transactional
    public void handleFriendRequest(Long userId, Long requestId, boolean accept) {
        FriendRequest request = friendRequestMapper.selectById(requestId);
        if (request == null || !request.getToUserId().equals(userId)) {
            throw new RuntimeException("无效的好友请求");
        }

        // 更新请求状态
        friendRequestMapper.updateStatus(requestId, accept ? 1 : 2);

        if (accept) {
            // 检查数据表中是否已经有记录只是之前被拒绝
            Contact contact = contactMapper.selectByUserIdAndFriendId(userId, request.getFromUserId());
            if (contact != null) {
                contact.setStatus(1);
                contactMapper.update(contact);
            }else{
                // 双向添加好友关系
                ContactDto dto = new ContactDto();
                dto.setFriendId(request.getFromUserId());
                User user = userMapper.selectById(request.getFromUserId());
                dto.setRemark(user.getNickname());
                dto.setCategory("我的好友");
                addContact(userId, dto);

                dto = new ContactDto();
                dto.setFriendId(userId);
                User user1 = userMapper.selectById(userId);
                dto.setRemark(user1.getNickname());
                dto.setCategory("我的好友");
                addContact(request.getFromUserId(), dto);
            }

            // 通过WebSocket通知申请方
            webSocketServer.sendMessage(
                    request.getFromUserId(),
                    "FRIEND_REQUEST_ACCEPTED",
                    userId);
        }
    }

    @Override
    public List<FriendRequestVo> getPendingRequests(Long userId) {
        return friendRequestMapper.selectByToUserId(userId)
                .stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    private FriendRequestVo convertToVo(FriendRequest request) {
        FriendRequestVo vo = new FriendRequestVo();
        BeanUtils.copyProperties(request, vo);

        // 获取发送者信息
        User sender = userMapper.selectById(request.getFromUserId());
        if (sender != null) {
            vo.setSenderName(sender.getUsername());
            vo.setSenderAvatar(sender.getAvatar());
        }

        return vo;
    }
}